package com.ns.school.common.utils;

import com.alibaba.fastjson2.JSONObject;
import com.ns.school.common.constant.StaticVar;
import org.apache.commons.lang3.StringUtils;

import jakarta.servlet.http.HttpServletRequest;

import java.io.StringReader;
import java.io.StringWriter;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

public class StrUtil extends cn.hutool.core.util.StrUtil {

    private static final Random RANDOM = new SecureRandom();
    private static final String BASE_INT = "012356789";
    private static final String BASE_STR = "abcdefghijklmnopqrstuvwxyz012356789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    // 不可见字符
    private static final List<String> INVISIBLE_STR = Arrays.asList("\u202e", "\u202d", "\u202c");
    // 手机号隐藏规则
    private static final String HIDE_TEL = "(\\d{3})\\d{4}(\\d{4})";
    private static final String HIDE_TEL$ = "$1****$2";
    // 全局正则表达式
    private static final Pattern SPACE_PATTERN = Pattern.compile("\\s*|\t|\r|\n");
    private static final Pattern TEL_PATTERN = Pattern.compile("^1[3-9][0-9]{9}$");
    private static final Pattern TEL_PATTERN_PLUS = Pattern.compile("^\\+\\d+$");
    private static final Pattern ACCOUNT_NO_PATTERN = Pattern.compile("^[A-Za-z0-9]+$");
    private static final Pattern NUM_PATTERN = Pattern.compile("^[0-9]*$");
    private static final Pattern MONEY_PATTERN = Pattern.compile("^((\\d{1,8})|(\\d{1,8}\\.\\d{1,2}))$");
    private static final Pattern PERIMETER_PATTERN = Pattern.compile("^((\\d{1,5})|(\\d{1,5}\\.\\d))$");
    private static final Pattern INTEGER_PATTERN = Pattern.compile("^[-+]?[0-9]*$");

    /**
     * 删除各类空格(你看到的空格不一定是空格)
     *
     * @param s
     * @return String
     */
    public static String deleteAllBlankSpace(String s) {
        if (isEmpty(s)) {
            return "";
        }
        s = SPACE_PATTERN.matcher(s).replaceAll("").replaceAll("\\s*", "").replaceAll(" ", "").trim();
        return removeInvisible(s);
    }

    /**
     * 生成指定长度的随机字符串
     *
     * @param l
     * @return
     */
    public static String getRandomStr(int l) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < l; i++) {
            sb.append(BASE_STR.charAt(RANDOM.nextInt(BASE_STR.length())));
        }
        return sb.toString();
    }

    /**
     * 生成指定长度的随机数字
     *
     * @param l
     * @return
     */
    public static String getRandomInt(int l) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < l; i++) {
            sb.append(BASE_INT.charAt(RANDOM.nextInt(BASE_INT.length())));
        }
        return sb.toString();
    }

    /**
     * 获取一个随机生成的流水号
     *
     * @return 16位的数字流水号 Long 长整型
     */
    public static Long getRandomOrderId() {
        return Long.parseLong(getRandomOrderIdStr());
    }

    /**
     * 获取一个随机生成的流水号
     *
     * @return 16位的数字流水号 Long 长整型
     */
    public static String getRandomOrderIdStr() {
        return System.currentTimeMillis() + getRandomInt(3);
    }

    /**
     * 根据AU信息获取浏览器类型
     *
     * @param request
     * @return String
     */
    public static String getBorwserName(HttpServletRequest request) {
        String agent = request.getHeader("User-Agent");
        if (!hasText(agent)) {
            return agent;
        }
        agent = agent.toLowerCase();
        if (agent.indexOf("micromessenger") > 0) {
            return "wx";
        } else if (agent.indexOf("weibo") > 0) {
            return "wb";
        } else if (agent.indexOf("mqqbrowser") > 0) {
            return "qq";
        } else {
            return "else";
        }
    }

    /**
     * 将map转成json字符串
     *
     * @param map
     * @return
     */
    public static JSONObject parseMapToWeChatMessageJson(Map<String, String> map) {
        JSONObject data = new JSONObject();
        for (Map.Entry<String, String> entity : map.entrySet()) {
            JSONObject json = new JSONObject();
            json.put("value", entity.getValue());
            json.put("color", "#0044BB");
            data.put(entity.getKey(), json);
        }
        return data;
    }

    /**
     * 判断字符串是否是合法日期
     *
     * @param s
     * @return
     */
    public static boolean isValidDate(String s, SimpleDateFormat... dfs) {
        for (SimpleDateFormat df : dfs) {
            try {
                df.setLenient(false);
                if (df.format(df.parse(s)).equals(s)) {
                    return true;
                }
            } catch (Exception e) {
                // todo
            }
        }
        return false;
    }

    /**
     * 判断字符串是否是合法日期 :yyyyMMdd
     *
     * @param s
     * @return
     */
    public static boolean isValidDate(String s) {
        return isValidDate(s, new SimpleDateFormat("yyyyMMdd"),
                new SimpleDateFormat("yyyyMMd"),
                new SimpleDateFormat("yyyyMdd"),
                new SimpleDateFormat("yyyyMd"));
    }

    /**
     * 判断字符串是否是合法日期 :yyyy-MM-dd
     *
     * @param s
     * @return
     */
    public static boolean isValidDate2(String s) {
        return isValidDate(s, new SimpleDateFormat("yyyy-MM-dd"),
                new SimpleDateFormat("yyyy-MM-d"),
                new SimpleDateFormat("yyyy-M-dd"),
                new SimpleDateFormat("yyyy-M-d"));
    }

    /**
     * 判断字符串是否是合法日期 :yyyy/MM/dd
     *
     * @param s
     * @return
     */
    public static boolean isValidDate3(String s) {
        return isValidDate(s, new SimpleDateFormat("yyyy/MM/dd"),
                new SimpleDateFormat("yyyy/MM/d"),
                new SimpleDateFormat("yyyy/M/dd"),
                new SimpleDateFormat("yyyy/M/d"));
    }

    /**
     * 判断字符串中是否包含某个数字
     *
     * @param s
     * @param n
     * @return
     * @author chenx 2017.11.17
     */
    public static boolean isContainsNum(String s, Integer n) {
        List<Integer> list = strToList(s);
        return list.contains(n);
    }

    /**
     * 把带有,的字符串截取转成list
     *
     * @param s
     * @return
     */
    public static List<Integer> strToList(String s) {
        List<Integer> list = new ArrayList<Integer>();
        if (isNotEmpty(s)) {
            if (s.contains(",")) {
                String[] arr = s.split(",");
                for (String t : arr) {
                    list.add(Integer.valueOf(t));
                }
            } else {
                list.add(Integer.valueOf(s));
            }
        }
        return list;
    }

    /**
     * 判断手机号码格式是否正确
     *
     * @param phone
     * @return
     */
    public static boolean isPhoneNumber(String phone) {
        if (isEmpty(phone)) {
            return false;
        }
        if (phone.charAt(0) == '+') {
            return TEL_PATTERN_PLUS.matcher(phone).matches();
        }
        return TEL_PATTERN.matcher(phone).matches();
    }

    /**
     * 判断手机号码格式是否正确
     *
     * @param phone
     * @return
     */
    public static boolean isMobile(String phone) {
        return isPhoneNumber(phone);
    }

    /**
     * 判断手机号码格式是否正确
     *
     * @param phone
     * @return
     */
    public static boolean isTelphone(String phone) {
        return isPhoneNumber(phone);
    }

    /**
     * 判断是否合法登录账户
     *
     * @param login
     * @return
     */
    public static boolean isLoginAccount(String login) {
        if (isEmpty(login)) {
            return false;
        }
        return ACCOUNT_NO_PATTERN.matcher(login).matches();
    }

    /**
     * 判断字符 不是空的 （空格也算空）
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean notBlank(Object str) {
        return !isBlank(str);
    }

    /**
     * 判断字符 不是空的 （空格也算空）
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean notBlank(String str) {
        return !isBlank(str);
    }

    /**
     * 判断字符串是否为空（空格也算空）
     */
    public static boolean isBlank(final CharSequence cs) {
        if (cs == null) {
            return true;
        }
        final int strLen = cs.length();
        if (strLen == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串是否为空（空格也算空）
     *
     * @param str 字符串
     * @return boolean
     */
    public static boolean isBlank(final Object str) {
        if (str == null) {
            return true;
        } else if (str instanceof String) {
            return isBlank((String) str);
        }
        return false;
    }

    /**
     * 判断字符串是否不为空
     *
     * @param s
     * @return
     */
    public static boolean notEmpty(Object s) {
        return !isEmpty(s);
    }

    /**
     * 判断字符串是否不为空
     *
     * @param s
     * @return
     */
    public static boolean notEmpty(final CharSequence s) {
        return !isEmpty(s);
    }

    /**
     * 判断字符串是否为空
     *
     * @param s
     * @return
     */
    public static boolean isEmpty(Object s) {
        if (s == null) {
            return true;
        } else if (s instanceof String) {
            return isEmpty((String) s);
        }
        return false;
    }

    /**
     * <p>Checks if a CharSequence is empty ("") or null.</p>
     */
    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * 判断字符串是否为空
     *
     * @param s
     * @return
     */
    public static boolean isEmptyNull(Object s) {
        return (s == null || "".equals(s) || "null".equals(s));
    }

    /**
     * <pre class="code">
     * StringUtil.hasText(null) = false
     * StringUtil.hasText("") = false
     * StringUtil.hasText(" ") = false
     * StringUtil.hasText("12345") = true
     * StringUtil.hasText(" 12345 ") = true
     * </pre>
     */
    public static boolean hasText(String s) {
        return notBlank(s);
    }

    public static boolean hasNoText(String s) {
        return !hasText(s);
    }

    /**
     * 判断是否是类似"2,4,7,3"
     *
     * @param s
     * @return
     */
    public static boolean isArrStr(final String s) {
        if (isEmpty(s)) {
            return true;
        }
        return NUM_PATTERN.matcher(s.replace(",", "")).matches();
    }

    /**
     * 判断是否为自然数(>=0的整数)
     *
     * @param s
     * @return
     */
    public static boolean isNum(String s) {
        if (isEmpty(s)) {
            return false;
        }
        return NUM_PATTERN.matcher(s).matches();
    }

    public static boolean isNumeric(String str) {
        return isNum(str);
    }

    public static boolean isDouble(String str) {
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 判断是否为金额(小数位可选,最多为2位)
     *
     * @param s
     * @return
     */
    public static boolean isMoney(String s) {
        if (isEmpty(s)) {
            return false;
        }
        return MONEY_PATTERN.matcher(s).matches();
    }

    /**
     * 判断是否为套餐销课次数(小数位可选,最多为1位)
     *
     * @param s
     * @return
     */
    public static boolean isPerimeter(String s) {
        if (isEmpty(s)) {
            return false;
        }
        return PERIMETER_PATTERN.matcher(s).matches();
    }

    /**
     * 判断是否为整数
     *
     * @param s 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static boolean isInteger(String s) {
        if (isEmpty(s)) {
            return false;
        }
        return INTEGER_PATTERN.matcher(s).matches();
    }

    /**
     * 判断是否不为整数
     *
     * @param s 传入的字符串
     * @return 不是整数返回true, 否则返回false
     */
    public static boolean notInteger(String s) {
        return !isInteger(s);
    }

    /**
     * 得到一个32位的uuid值
     *
     * @return
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 得到一个16位的uuid值
     *
     * @return
     */
    public static String getUUID16() {
        return getUUID().substring(0, 16);
    }

    /**
     * 自动补齐URL地址
     *
     * @param url
     * @return
     */
    public static String httpUrlFill(String url) {
        if (hasText(url) && !url.startsWith("http")) {
            return "https:" + url;
        }
        return url;
    }

    /**
     * 比较两个字符串是否不相等
     *
     * @param a
     * @param b
     * @return
     */
    public static boolean notEquals(String a, String b) {
        return !equals(a, b);
    }

    /**
     * 比较两个字符串是否相等
     *
     * @param a
     * @param b
     * @return
     */
    public static boolean equals(String a, String b) {
        if (a == null && b == null) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        return a.equals(b);
    }

    /**
     * 比较两个数字是否相等
     *
     * @param a
     * @param b
     * @return
     */
    public static boolean equals(Integer a, Integer b) {
        if (a == null && b == null) {
            return true;
        }
        if (a == null || b == null) {
            return false;
        }
        return a.intValue() == b.intValue();
    }

    /**
     * 比较数字data是否和集合中任一个相等
     *
     * @param data
     * @param any
     * @return
     */
    public static boolean equalsAny(final Integer data, final int... any) {
        if (data == null && any == null) {
            return true;
        }
        if (data == null || any == null) {
            return false;
        }
        for (int i : any) {
            if (data == i) {
                return true;
            }
        }
        return false;
    }

    /**
     * 字符串转换unicode
     *
     * @param string
     * @return
     */
    public static String stringToUnicode(String string) {
        StringBuilder unicode = new StringBuilder();
        for (int i = 0; i < string.length(); i++) {
            char c = string.charAt(i); // 取出每一个字符
            unicode.append("\\u").append(Integer.toHexString(c));// 转换为unicode
        }
        return unicode.toString();
    }

    /**
     * unicode 转字符串
     *
     * @param unicode
     * @return
     */
    public static String unicodeToString(String unicode) {
        StringBuilder string = new StringBuilder();
        String[] hex = unicode.split("\\\\u");
        for (int i = 1; i < hex.length; i++) {
            int data = Integer.parseInt(hex[i], 16);// 转换出每一个代码点
            string.append((char) data);// 追加成string
        }
        return string.toString();
    }

    /**
     * 移除不可见字符-\u202e,\u202d,\u202c
     *
     * @param str
     * @return
     */
    public static String removeInvisible(String str) {
        if (isEmpty(str)) {
            return str;
        }
        for (String inv : INVISIBLE_STR) {
            str = str.replaceAll(inv, "");
        }
        return str;
    }

    /**
     * 手机号脱敏
     *
     * @param tel
     * @return
     */
    public static String telHide(String tel) {
        if (isEmpty(tel)) {
            return tel;
        }
        return tel.replaceAll(HIDE_TEL, HIDE_TEL$);
    }

    /**
     * 将字符串转为整数-不合法的返回空
     *
     * @param str
     * @return
     */
    public static Integer str2Integer(String str) {
        if (hasText(str) && isInteger(str)) {
            return Integer.parseInt(str);
        }
        return null;
    }

    /**
     * MySQL的模糊查询时特殊字符转义
     *
     * @param param
     * @return
     */
    public static String escapeChar(String param) {
        if (hasText(param)) {
            return param.replace("_", "\\\\_").replace("%", "\\\\%");
        }
        return param;
    }

    public static boolean exist(Integer in, Integer[] ranges) {
        if (in == null || ranges.length < 1) {
            return false;
        }
        boolean exist = false;
        for (Integer range : ranges) {
            if (in.intValue() == range.intValue()) {
                exist = true;
                break;
            }
        }
        return exist;
    }

    /**
     * 根据指定的长度截取字符串
     *
     * @param str
     * @param size
     * @return
     */
    public static String interceptStr(String str, int size) {
        if (size <= 0) {
            throw new RuntimeException("size数据不合法,必须大于0!");
        }
        if (str == null || "".equals(str) || str.length() <= size) {
            return str;
        } else {
            return str.substring(0, size);
        }
    }

    public static String toLen(String str, Integer len) {
        if (isEmpty(str)) {
            return "00";
        }
        if (str.length() < len) {
            StringBuilder strBuilder = new StringBuilder(str);
            for (int i = len; i > strBuilder.length(); i--) {
                strBuilder.insert(0, "0");
            }
            str = strBuilder.toString();
        }
        return str;
    }

    /**
     * 给指定连接追加参数
     *
     * @param url   连接
     * @param query 参数集合
     * @return 携带参数的连接
     */
    public static String appendQuerys(String url, Map<String, String> query) {
        if (isBlank(url) || query == null || query.isEmpty()) {
            return url;
        }
        String ending = "";
        if (url.contains("#")) {
            String[] urls = url.split("#");
            url = urls[0];
            ending = "#" + urls[1];
        }
        url += url.contains("?") ? "&" : "?";
        StringBuilder sb = new StringBuilder();
        for (String key : query.keySet()) {
            sb.append(key).append("=").append(query.get(key)).append("&");
        }
        // 去除最后一个字符&
        url += sb.deleteCharAt(sb.length() - 1).toString() + ending;
        return url;
    }

    /**
     * 编码
     *
     * @param str
     * @return
     */
    public static String encode(String str) {
        return URLEncoder.encode(str, StandardCharsets.UTF_8);
    }

    /**
     * 解码
     *
     * @param str
     * @return
     */
    public static String decode(String str) {
        return URLDecoder.decode(str, StandardCharsets.UTF_8);
    }

    /**
     * 判断是数字加逗号组成的字符
     *
     * @param param
     * @return 是->返回true; 否->返回false
     */
    public static boolean isCorrectInData(final String param) {
        return isNum(param.replace(StaticVar.COMMA, StaticVar.EMPTY));
    }

    /**
     * 判断不是数字加逗号组成的字符
     *
     * @param param
     * @return
     */
    public static boolean isNotCorrectInData(final String param) {
        return !isCorrectInData(param);
    }

    /**
     * 生成随机文件名(纯数字19位)
     *
     * @return
     */
    public static String getRandomFileName() {
        return System.currentTimeMillis() + getRandomInt(6);
    }

    public static String dateReplace2Int(final String str) {
        if (str == null) {
            return null;
        }
        return str.replace(StaticVar.SPACE, StaticVar.EMPTY).replace(StaticVar.DASH, StaticVar.EMPTY).replace(StaticVar.COLON, StaticVar.EMPTY);
    }

    @SafeVarargs
    public static <T> String join(final T... elements) {
        return StringUtils.join(elements);
    }

    /**
     * 将集合用逗号拼接成字符串
     *
     * @param coll
     * @param <T>
     * @return
     */
    public static <T> String join(final Collection<T> coll) {
        if (coll == null || coll.isEmpty()) {
            return null;
        }
        return StringUtils.join(coll, COMMA);
    }

    public static <T> String join(final Iterable<?> iterable, final String separator) {
        return StringUtils.join(iterable, separator);
    }

    public static String join(final String[] array, final String separator) {
        return StringUtils.join(array, separator);
    }

    public static String join(final Object[] array, final String separator) {
        return StringUtils.join(array, separator);
    }

    /**
     * 将集合去重,然后用逗号拼接成字符串
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> String joinNoRepeat(final List<T> list) {
        if (list == null) {
            return null;
        }
        CollUtil.removeRepeat(list);
        return StringUtils.join(list.iterator(), COMMA);
    }

    /**
     * 将数组用逗号拼接成字符串
     *
     * @param array
     * @return
     */
    public static String joinArr(final Object[] array) {
        if (array == null || array.length == 0) {
            return null;
        }
        return StringUtils.join(array, COMMA);
    }

    /**
     * 允许空值的字符切割
     * ",cd,ef,",    = ["", cd", "ef", ""]
     *
     * @param str
     * @return
     */
    public static String[] splitN(final String str) {
        return splitN(str, COMMA);
    }

    /**
     * 允许空值的字符切割
     * ",cd,ef,",    = ["", cd", "ef", ""]
     *
     * @param str
     * @return
     */
    public static String[] splitN(final String str, final String split) {
        if (str == null || str.isEmpty()) {
            return null;
        }
        return StringUtils.splitPreserveAllTokens(str, split);
    }

    public static String[] split(final String str, final String separatorChars) {
        return StringUtils.split(str, separatorChars);
    }

    public static String capitalize(final String str) {
        return StringUtils.capitalize(str);
    }

    public static String uncapitalize(final String str) {
        return StringUtils.uncapitalize(str);
    }

    public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
        return StringUtils.replaceEach(text, searchList, replacementList);
    }

    /**
     * 判断给定对象是否null,是则返回默认值,否则返回对象自己
     *
     * @param obj
     * @param def
     * @param <T>
     * @return
     */
    public static <T> T defaultIfNull(T obj, T def) {
        if (obj == null) {
            return def;
        }
        return obj;
    }

    /**
     * 将对象转换为字符串（空对象转换为""）
     *
     * @param str
     * @return
     */
    public static String toString(Object str) {
        if (isEmpty(str)) {
            return EMPTY;
        } else {
            if (str instanceof String) {
                return (String) str;
            }
            return str.toString();
        }
    }

    /**
     * 将字符转换成int数字
     *
     * @param str
     * @return
     */
    public static Integer toInteger(String str) {
        if (isEmpty(str)) {
            return null;
        } else {
            return Integer.parseInt(str);
        }
    }

    /**
     * 将字符转换成int数字
     *
     * @param str
     * @return
     */
    public static int toInteger(String str, int def) {
        if (isEmpty(str)) {
            return def;
        } else {
            return Integer.parseInt(str);
        }
    }

    /**
     * 将字符转换成long数字
     *
     * @param str
     * @return
     */
    public static Long toLong(String str) {
        if (isEmpty(str)) {
            return null;
        } else {
            return Long.parseLong(str);
        }
    }

    /**
     * 将字符转换成long数字
     *
     * @param str
     * @return
     */
    public static long toLong(String str, long def) {
        if (isEmpty(str)) {
            return def;
        } else {
            return Long.parseLong(str);
        }
    }

    /**
     * 将字符转换成double数字
     *
     * @param str
     * @return
     */
    public static Double toDouble(String str) {
        if (isEmpty(str)) {
            return null;
        } else {
            return Double.valueOf(str);
        }
    }

    public static String defaultString(final String str) {
        return Objects.toString(str, EMPTY);
    }

    public static String stripEnd(final String str, final String stripChars) {
        return StringUtils.stripEnd(str, stripChars);
    }

    public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
        return StringUtils.indexOf(seq, searchSeq);
    }

    public static String leftPad(final Object str, final int size, String padStr) {
        if (str == null) {
            return null;
        }
        return StringUtils.leftPad(str.toString(), size, padStr);
    }

    public static String leftPad(final String str, final int size, final char padChar) {
        if (str == null) {
            return null;
        }
        return StringUtils.leftPad(str, size, padChar);
    }

    public static String rightPad(final Object str, final int size, String padStr) {
        if (str == null) {
            return null;
        }
        return StringUtils.rightPad(str.toString(), size, padStr);
    }

    public static String rightPad(final String str, final int size, final char padChar) {
        if (str == null) {
            return null;
        }
        return StringUtils.rightPad(str, size, padChar);
    }

    public static String substringAfter(final String str, final int separator) {
        return StringUtils.substringAfter(str, separator);
    }

    public static String substringAfter(final String str, final String separator) {
        return StringUtils.substringAfter(str, separator);
    }

    public static String substringBefore(final String str, final int separator) {
        return StringUtils.substringBefore(str, separator);
    }

    public static String substringBefore(final String str, final String separator) {
        return StringUtils.substringBefore(str, separator);
    }

    public static String substringAfterLast(final String str, final int separator) {
        return StringUtils.substringAfterLast(str, separator);
    }

    public static String substringAfterLast(final String str, final String separator) {
        return StringUtils.substringAfterLast(str, separator);
    }

    public static String substringBetween(final String str, final String tag) {
        return StringUtils.substringBetween(str, tag);
    }

    public static String substringBetween(final String str, final String open, final String close) {
        return StringUtils.substringBetween(str, open, close);
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @return 结果
     */
    public static String substring(final String str, int start) {
        if (str == null) {
            return EMPTY;
        }
        return StringUtils.substring(str, start);
    }

    /**
     * 截取字符串
     *
     * @param str   字符串
     * @param start 开始
     * @param end   结束
     * @return 结果
     */
    public static String substring(final String str, int start, int end) {
        if (str == null) {
            return EMPTY;
        }
        return StringUtils.substring(str, start, end);
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs) {
        if (str != null && strs != null) {
            for (String s : strs) {
                if (str.equalsIgnoreCase(trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获得StringReader
     *
     * @param str 字符串
     * @return StringReader
     */
    public static StringReader getReader(CharSequence str) {
        if (null == str) {
            return null;
        }
        return new StringReader(str.toString());
    }

    /**
     * 获得StringWriter
     *
     * @return StringWriter
     */
    public static StringWriter getWriter() {
        return new StringWriter();
    }

    /**
     * {@link CharSequence} 转为字符串，null安全
     *
     * @param cs {@link CharSequence}
     * @return 字符串
     */
    public static String str(CharSequence cs) {
        return null == cs ? null : cs.toString();
    }
}
